package com.hts.redis.atomic;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * redis 操作数据
 * 自增序列 自减序列
 * @author 洪松
 */
@Service
public class AtomicRedisInteger {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private DefaultRedisScript<Long> incrementRedisScript;
    private DefaultRedisScript<Long> decrementRedisScript;

    @PostConstruct
    public void init() {

        String increment = """
                if (redis.call('exists',KEYS[1]) == 0) then
                    local ttl = tonumber(ARGV[1])
                    
                    if(ttl == -1)then
                       redis.call('set',KEYS[1],1) 
                    else
                       redis.call('set',KEYS[1],1,'EX',ARGV[1])  
                    end  
                    return 1
                else
                    local value = tonumber(redis.call('get',KEYS[1])) +1
                    local ttl = tonumber(ARGV[1])
                    
                    if(ttl == -1)then
                       redis.call('set',KEYS[1],value) 
                    else
                       redis.call('set',KEYS[1],value,'EX',ARGV[1])  
                    end        
         
                    return value
                end
                """;
        incrementRedisScript = new DefaultRedisScript<>();
        incrementRedisScript.setScriptText(increment);
        incrementRedisScript.setResultType(Long.class);


        String decrement = """
                if (redis.call('exists',KEYS[1]) == 0) then
                  
                    return 0
                else
                    local value = tonumber(redis.call('get',KEYS[1])) -1
                    local ttl = tonumber(ARGV[1])
                    
                    if(ttl == -1)then
                       redis.call('set',KEYS[1],value) 
                    else
                       redis.call('set',KEYS[1],value,'EX',ARGV[1])  
                    end        
         
                    return value
                end
                """;

        decrementRedisScript = new DefaultRedisScript<>();
        decrementRedisScript.setScriptText(decrement);
        decrementRedisScript.setResultType(Long.class);
    }

    /**
     * 先自增在获取值  默认失效时间2天
     * @param key
     * @return
     */
    public Long incrementGetDefault(String key) {
        ArrayList<String> keys = new ArrayList<>();
        keys.add(key);
        int i = 60 * 60 * 24 * 2;
        return redisTemplate.execute(incrementRedisScript, keys, i);
    }

    /**
     * 先自减在获取值  默认失效时间2天
     * @param key
     * @return
     */
    public Long decrementGetDefault(String key) {
        ArrayList<String> keys = new ArrayList<>();
        keys.add(key);
        return redisTemplate.execute(decrementRedisScript, keys, 60*60*24*2);
    }

    /**
     * 自增获取
     * @param key
     * @return
     */
    public Long incrementGet(String key) {
        ArrayList<String> keys = new ArrayList<>();
        keys.add(key);
        return redisTemplate.execute(incrementRedisScript, keys, -1);
    }

    /**
     * 自减获取
     * @param key
     * @return
     */
    public Long decrementGet(String key) {
        ArrayList<String> keys = new ArrayList<>();
        keys.add(key);
        return redisTemplate.execute(decrementRedisScript, keys, -1);
    }
}
